Popular Searches
Popular Course Categories
Popular Courses

Updating UI dynamically using setState()

Updating UI dynamically using setState()

Flutter Fundamentals

Updating UI Dynamically Using setState() in Flutter

In Flutter, the user interface is built from the current state of the application. When a value changes during runtime, the UI needs to reflect that new value. The setState() method is the basic mechanism used inside a State object to notify Flutter that the internal state has changed and that the UI may need to be rebuilt.

When setState() is called, Flutter executes the callback synchronously and schedules the associated State object for rebuilding. If a state value is changed directly without notifying Flutter, the UI may not update to reflect the new value. :contentReference[oaicite:0]{index=0}


1. Learning Objectives

After completing this topic, you will understand:

  • What dynamic UI updating means in Flutter.
  • Why UI needs to be rebuilt when state changes.
  • How setState() updates the UI.
  • How to update text dynamically.
  • How to update counters dynamically.
  • How to change colors dynamically.
  • How to show and hide widgets dynamically.
  • How to update lists dynamically.
  • How to handle buttons, switches, checkboxes, sliders, and dropdowns.
  • How to update UI after asynchronous operations.
  • How to avoid common setState() mistakes.

2. What Does Dynamic UI Mean?

A dynamic UI is an interface whose content, appearance, or behavior changes while the application is running.

For example:

  • A counter changes from 0 to 1.
  • A button changes its text after being clicked.
  • A password field changes between visible and hidden.
  • A favorite icon changes when selected.
  • A loading indicator appears while data is loading.
  • A product quantity changes when the user taps plus or minus.
  • A new item appears in a list.
  • A selected dropdown value changes.

Flutter uses state changes to determine when the UI should display new information.


3. Why Does the UI Need to Update?

Consider this variable:

int counter = 0;

The UI may display:

Text('$counter')

If the value changes:

counter++;

the Dart variable changes, but changing the variable alone does not tell Flutter that the widget needs to rebuild.

Instead, when the value affects the UI, use:

setState(() {
  counter++;
});

This tells Flutter that the state changed and the associated UI may need to be rebuilt. :contentReference[oaicite:1]{index=1}


4. Basic Dynamic UI Flow

User Action
     ↓
Event Callback
     ↓
setState()
     ↓
State Variable Changes
     ↓
Flutter Schedules Build
     ↓
build() Runs
     ↓
New Widget Configuration
     ↓
Updated UI

For example, when a user presses an Increase button:

onPressed: () {
  setState(() {
    counter++;
  });
}

Flutter rebuilds the relevant widget using the new value.


5. Basic StatefulWidget Structure

Dynamic UI updates using setState() normally happen inside a StatefulWidget.

class CounterScreen extends StatefulWidget {
  const CounterScreen({super.key});

  @override
  State createState() => _CounterScreenState();
}

class _CounterScreenState extends State {
  int counter = 0;

  @override
  Widget build(BuildContext context) {
    return Text('$counter');
  }
}

The mutable value is stored in the State object. The build() method reads that value and creates the UI.


6. First Dynamic UI Example: Counter

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: CounterScreen(),
    );
  }
}

class CounterScreen extends StatefulWidget {
  const CounterScreen({super.key});

  @override
  State createState() => _CounterScreenState();
}

class _CounterScreenState extends State {
  int counter = 0;

  void increaseCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Dynamic Counter'),
      ),
      body: Center(
        child: Text(
          '$counter',
          style: const TextStyle(
            fontSize: 40,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: increaseCounter,
        child: const Icon(Icons.add),
      ),
    );
  }
}

How it works

  1. The initial value of counter is 0.
  2. The Text widget displays the counter.
  3. The user presses the floating action button.
  4. increaseCounter() is called.
  5. setState() changes the value.
  6. Flutter schedules the widget for rebuilding.
  7. The build() method uses the new counter value.
  8. The user sees the updated number.

7. Updating Text Dynamically

Text can be changed dynamically using a state variable.

String message = 'Hello Flutter';

void changeMessage() {
  setState(() {
    message = 'Welcome to Flutter';
  });
}

Display it using:

Text(message)

Complete example:

Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Text(
      message,
      style: const TextStyle(fontSize: 24),
    ),
    ElevatedButton(
      onPressed: changeMessage,
      child: const Text('Change Message'),
    ),
  ],
)

8. Updating a Button Text Dynamically

The text of a button can also change according to the current state.

bool isSubmitted = false;

void submit() {
  setState(() {
    isSubmitted = true;
  });
}

UI:

ElevatedButton(
  onPressed: submit,
  child: Text(
    isSubmitted ? 'Submitted' : 'Submit',
  ),
)

Initially, the button displays Submit. After clicking it, the button displays Submitted.


9. Updating UI with Boolean State

Boolean variables are very useful for dynamic UI.

bool isVisible = false;

void toggleVisibility() {
  setState(() {
    isVisible = !isVisible;
  });
}

Use the value to conditionally display a widget:

Column(
  children: [
    if (isVisible)
      const Text(
        'This content is now visible',
      ),
    ElevatedButton(
      onPressed: toggleVisibility,
      child: const Text('Show/Hide'),
    ),
  ],
)

10. Show and Hide Widgets Dynamically

A common requirement in applications is to show or hide content based on user interaction.

bool showDetails = false;

void toggleDetails() {
  setState(() {
    showDetails = !showDetails;
  });
}

UI:

Column(
  children: [
    ElevatedButton(
      onPressed: toggleDetails,
      child: Text(
        showDetails ? 'Hide Details' : 'Show Details',
      ),
    ),
    if (showDetails)
      const Card(
        child: Padding(
          padding: EdgeInsets.all(16),
          child: Text(
            'Additional product details are displayed here.',
          ),
        ),
      ),
  ],
)

11. Updating Colors Dynamically

The appearance of a widget can be changed using state.

Color boxColor = Colors.blue;

void changeColor() {
  setState(() {
    boxColor = Colors.green;
  });
}

Use it in the UI:

Container(
  width: 150,
  height: 150,
  color: boxColor,
)

Complete example:

Column(
  children: [
    Container(
      width: 150,
      height: 150,
      color: boxColor,
    ),
    const SizedBox(height: 20),
    ElevatedButton(
      onPressed: changeColor,
      child: const Text('Change Color'),
    ),
  ],
)

12. Dynamically Changing Multiple Colors

List colors = [
  Colors.red,
  Colors.green,
  Colors.blue,
];

int selectedColor = 0;

void changeColor() {
  setState(() {
    selectedColor =
        (selectedColor + 1) % colors.length;
  });
}

Display:

Container(
  width: 150,
  height: 150,
  color: colors[selectedColor],
)

13. Updating UI with Switch

A switch is commonly used to represent an on/off state.

bool isEnabled = false;

Switch(
  value: isEnabled,
  onChanged: (value) {
    setState(() {
      isEnabled = value;
    });
  },
)

Display the current state:

Text(
  isEnabled ? 'Enabled' : 'Disabled',
)

14. Dynamic Dark Mode Example

bool isDarkMode = false;

void toggleTheme() {
  setState(() {
    isDarkMode = !isDarkMode;
  });
}

The switch can update the UI:

Switch(
  value: isDarkMode,
  onChanged: (value) {
    setState(() {
      isDarkMode = value;
    });
  },
)

For a complete application-wide theme change, the state would normally be connected to the application's ThemeData or a broader state-management solution.


15. Updating UI with Checkbox

bool isAccepted = false;

Checkbox(
  value: isAccepted,
  onChanged: (value) {
    setState(() {
      isAccepted = value ?? false;
    });
  },
)

Dynamic text:

Text(
  isAccepted
      ? 'Terms accepted'
      : 'Please accept the terms',
)

16. Dynamic Login Button

A login button can change its state when the login process begins.

bool isLoading = false;

Future login() async {
  setState(() {
    isLoading = true;
  });

  await Future.delayed(
    const Duration(seconds: 2),
  );

  if (!mounted) return;

  setState(() {
    isLoading = false;
  });
}

UI:

ElevatedButton(
  onPressed: isLoading ? null : login,
  child: isLoading
      ? const CircularProgressIndicator()
      : const Text('Login'),
)

17. Why Use setState() for Loading UI?

Before the operation starts:

setState(() {
  isLoading = true;
});

Flutter rebuilds the UI and displays the loading state.

After the operation completes:

setState(() {
  isLoading = false;
});

Flutter rebuilds the UI again and displays the normal button.


18. Updating a List Dynamically

Lists are another common example of dynamic UI.

List fruits = [
  'Apple',
  'Banana',
];

void addFruit() {
  setState(() {
    fruits.add('Orange');
  });
}

Display the list:

ListView.builder(
  itemCount: fruits.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(fruits[index]),
    );
  },
)

After addFruit() executes, the list is rebuilt and the new item can appear in the UI.


19. Adding and Removing Items Dynamically

List tasks = [];

void addTask(String task) {
  setState(() {
    tasks.add(task);
  });
}

void removeTask(int index) {
  setState(() {
    tasks.removeAt(index);
  });
}

UI:

ListView.builder(
  itemCount: tasks.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(tasks[index]),
      trailing: IconButton(
        icon: const Icon(Icons.delete),
        onPressed: () {
          removeTask(index);
        },
      ),
    );
  },
)

20. Complete Dynamic To-Do Example

import 'package:flutter/material.dart';

class TodoScreen extends StatefulWidget {
  const TodoScreen({super.key});

  @override
  State createState() => _TodoScreenState();
}

class _TodoScreenState extends State {
  final List tasks = [];
  final TextEditingController controller =
      TextEditingController();

  void addTask() {
    final task = controller.text.trim();

    if (task.isEmpty) return;

    setState(() {
      tasks.add(task);
      controller.clear();
    });
  }

  void removeTask(int index) {
    setState(() {
      tasks.removeAt(index);
    });
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Dynamic Todo App'),
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: controller,
                    decoration: const InputDecoration(
                      hintText: 'Enter task',
                    ),
                  ),
                ),
                IconButton(
                  onPressed: addTask,
                  icon: const Icon(Icons.add),
                ),
              ],
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: tasks.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(tasks[index]),
                  trailing: IconButton(
                    onPressed: () {
                      removeTask(index);
                    },
                    icon: const Icon(Icons.delete),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

Important Points

  • The list is stored in state.
  • addTask() adds a new item.
  • removeTask() removes an item.
  • Both methods call setState().
  • The ListView reads the latest list during the rebuild.
  • The TextEditingController is disposed of when the widget is removed.

21. Updating UI with Slider

double value = 50;

Slider(
  value: value,
  min: 0,
  max: 100,
  divisions: 100,
  label: value.round().toString(),
  onChanged: (newValue) {
    setState(() {
      value = newValue;
    });
  },
)

Display the value:

Text(
  'Value: ${value.toStringAsFixed(0)}',
)

As the slider moves, the state changes and the displayed value is updated.


22. Updating UI with DropdownButton

String selectedCity = 'Mumbai';

DropdownButton(
  value: selectedCity,
  items: const [
    DropdownMenuItem(
      value: 'Mumbai',
      child: Text('Mumbai'),
    ),
    DropdownMenuItem(
      value: 'Delhi',
      child: Text('Delhi'),
    ),
    DropdownMenuItem(
      value: 'Pune',
      child: Text('Pune'),
    ),
  ],
  onChanged: (value) {
    if (value == null) return;

    setState(() {
      selectedCity = value;
    });
  },
)

Display the selected value:

Text('Selected City: $selectedCity')

23. Updating UI with TextField

The onChanged callback of a TextField can be used to update UI state.

String username = '';

TextField(
  onChanged: (value) {
    setState(() {
      username = value;
    });
  },
)

Display the entered text:

Text(
  'Hello $username',
)

For large or complex forms, a TextEditingController, form validation, and more structured state handling may be more appropriate.


24. Dynamic Password Visibility

bool obscurePassword = true;

TextField(
  obscureText: obscurePassword,
  decoration: InputDecoration(
    labelText: 'Password',
    suffixIcon: IconButton(
      icon: Icon(
        obscurePassword
            ? Icons.visibility
            : Icons.visibility_off,
      ),
      onPressed: () {
        setState(() {
          obscurePassword = !obscurePassword;
        });
      },
    ),
  ),
)

The UI dynamically changes both the password visibility and the icon.


25. Dynamic Favorite Button

bool isFavorite = false;

IconButton(
  onPressed: () {
    setState(() {
      isFavorite = !isFavorite;
    });
  },
  icon: Icon(
    isFavorite
        ? Icons.favorite
        : Icons.favorite_border,
  ),
)

This is a common pattern in product, social media, and content applications.


26. Updating UI with Multiple State Variables

Several related state variables can be changed inside one setState() call.

int score = 0;
String status = 'Not Started';
bool completed = false;

void completeQuiz() {
  setState(() {
    score = 10;
    status = 'Completed';
    completed = true;
  });
}

The UI can use all three values:

Column(
  children: [
    Text('Score: $score'),
    Text('Status: $status'),
    Text(
      completed
          ? 'Quiz Completed'
          : 'Quiz In Progress',
    ),
  ],
)

27. Updating UI Dynamically with Conditions

Conditional expressions are commonly combined with state.

bool isLoggedIn = false;

Column(
  children: [
    Text(
      isLoggedIn
          ? 'Welcome back!'
          : 'Please log in',
    ),
    isLoggedIn
        ? const Text('Dashboard')
        : ElevatedButton(
            onPressed: () {
              setState(() {
                isLoggedIn = true;
              });
            },
            child: const Text('Login'),
          ),
  ],
)

28. Dynamic Shopping Cart Example

int quantity = 1;
final double price = 499;

void increaseQuantity() {
  setState(() {
    quantity++;
  });
}

void decreaseQuantity() {
  if (quantity > 1) {
    setState(() {
      quantity--;
    });
  }
}

double get totalPrice {
  return price * quantity;
}

UI:

Column(
  children: [
    Text('Price: ₹$price'),
    Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        IconButton(
          onPressed: decreaseQuantity,
          icon: const Icon(Icons.remove),
        ),
        Text('$quantity'),
        IconButton(
          onPressed: increaseQuantity,
          icon: const Icon(Icons.add),
        ),
      ],
    ),
    Text(
      'Total: ₹${totalPrice.toStringAsFixed(2)}',
      style: const TextStyle(
        fontSize: 20,
        fontWeight: FontWeight.bold,
      ),
    ),
  ],
)

Every quantity change causes the UI to display the new quantity and total price.


29. Updating UI After an Async Operation

Dynamic UI is frequently required when working with APIs, databases, files, or other asynchronous operations.

bool isLoading = false;
String message = '';

Future loadData() async {
  setState(() {
    isLoading = true;
    message = '';
  });

  await Future.delayed(
    const Duration(seconds: 2),
  );

  if (!mounted) return;

  setState(() {
    isLoading = false;
    message = 'Data loaded successfully';
  });
}

UI:

Column(
  children: [
    if (isLoading)
      const CircularProgressIndicator(),

    if (!isLoading)
      ElevatedButton(
        onPressed: loadData,
        child: const Text('Load Data'),
      ),

    Text(message),
  ],
)

30. Do Not Put Async Work Inside setState()

The callback passed to setState() must not be asynchronous. Flutter's API documentation specifies that the callback is executed synchronously and must not return a Future. :contentReference[oaicite:2]{index=2}

Incorrect:

setState(() async {
  await loadData();
  message = 'Done';
});

Correct:

Future loadData() async {
  await fetchData();

  if (!mounted) return;

  setState(() {
    message = 'Done';
  });
}

31. Why Check mounted?

An asynchronous operation can finish after the widget has already been removed from the widget tree. Calling setState() after the State has been disposed is an error.

Future loadData() async {
  final result = await fetchData();

  if (!mounted) return;

  setState(() {
    data = result;
  });
}

Flutter recommends cancelling the work that could trigger the update when possible. Checking mounted can be used as a safeguard before calling setState(). :contentReference[oaicite:3]{index=3}


32. Dynamic UI with Timer

import 'dart:async';

Timer? timer;
int seconds = 0;

@override
void initState() {
  super.initState();

  timer = Timer.periodic(
    const Duration(seconds: 1),
    (_) {
      if (!mounted) return;

      setState(() {
        seconds++;
      });
    },
  );
}

@override
void dispose() {
  timer?.cancel();
  super.dispose();
}

Display the timer:

Text(
  'Seconds: $seconds',
  style: const TextStyle(fontSize: 30),
)

Here the UI updates every second.


33. Updating UI Without setState()

Consider:

int counter = 0;

void increase() {
  counter++;
}

The value changes in Dart, but the UI may remain unchanged because Flutter was not notified that the State changed.

Correct:

void increase() {
  setState(() {
    counter++;
  });
}

Flutter's documentation specifically notes that changing state directly without setState() may not schedule a build, so the UI may not reflect the changed state. :contentReference[oaicite:4]{index=4}


34. Keep the setState() Callback Small

The setState() callback should contain the actual state modification rather than unrelated calculations or expensive operations.

Good:

setState(() {
  counter++;
});

Less appropriate:

setState(() {
  performLargeCalculation();
  saveDataToDatabase();
  makeApiRequest();
  counter++;
});

Better:

final result = performLargeCalculation();

await saveDataToDatabase(result);

if (!mounted) return;

setState(() {
  counter++;
});

Flutter recommends using setState() to wrap the actual state change rather than unrelated computation associated with that change. :contentReference[oaicite:5]{index=5}


35. Avoid Unnecessary setState() Calls

Calling setState() unnecessarily can cause additional rebuilding. Flutter's documentation notes that the direct overhead of setState() is small, but the indirect cost of rebuilding the affected widget subtree can be significant. :contentReference[oaicite:6]{index=6}

Instead of:

setState(() {
  counter++;
});

setState(() {
  message = 'Updated';
});

Related updates can often be combined:

setState(() {
  counter++;
  message = 'Updated';
});

36. Dynamic UI and build()

The build() method should describe what the UI should look like for the current state.

@override
Widget build(BuildContext context) {
  return Text(
    counter.toString(),
  );
}

When the state changes:

setState(() {
  counter++;
});

Flutter schedules a build, and the build() method reads the updated counter.


37. Dynamic UI with Icon Changes

bool isPlaying = false;

IconButton(
  onPressed: () {
    setState(() {
      isPlaying = !isPlaying;
    });
  },
  icon: Icon(
    isPlaying
        ? Icons.pause
        : Icons.play_arrow,
  ),
)

This pattern can be used for play/pause controls, expand/collapse buttons, favorite buttons, and many other interactive elements.


38. Dynamic Expand and Collapse UI

bool expanded = false;

void toggleExpanded() {
  setState(() {
    expanded = !expanded;
  });
}

UI:

Column(
  children: [
    ListTile(
      title: const Text('Flutter'),
      trailing: IconButton(
        onPressed: toggleExpanded,
        icon: Icon(
          expanded
              ? Icons.expand_less
              : Icons.expand_more,
        ),
      ),
    ),
    if (expanded)
      const Padding(
        padding: EdgeInsets.all(16),
        child: Text(
          'Flutter is a UI toolkit for building '
          'applications from a single codebase.',
        ),
      ),
  ],
)

39. Dynamic Form Validation

State can also control validation messages.

String email = '';
String errorMessage = '';

void validateEmail() {
  setState(() {
    if (email.contains('@')) {
      errorMessage = '';
    } else {
      errorMessage = 'Please enter a valid email address';
    }
  });
}

UI:

Column(
  children: [
    TextField(
      onChanged: (value) {
        email = value;
      },
    ),
    if (errorMessage.isNotEmpty)
      Text(
        errorMessage,
        style: const TextStyle(
          color: Colors.red,
        ),
      ),
    ElevatedButton(
      onPressed: validateEmail,
      child: const Text('Validate'),
    ),
  ],
)

40. Complete Dynamic Profile Example

class ProfileScreen extends StatefulWidget {
  const ProfileScreen({super.key});

  @override
  State createState() => _ProfileScreenState();
}

class _ProfileScreenState extends State {
  String name = 'Manish';
  bool isFollowing = false;
  int followers = 100;

  void toggleFollow() {
    setState(() {
      isFollowing = !isFollowing;

      if (isFollowing) {
        followers++;
      } else {
        followers--;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Profile'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const CircleAvatar(
              radius: 50,
              child: Icon(Icons.person, size: 50),
            ),
            const SizedBox(height: 16),
            Text(
              name,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
            const SizedBox(height: 10),
            Text('Followers: $followers'),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: toggleFollow,
              child: Text(
                isFollowing ? 'Following' : 'Follow',
              ),
            ),
          ],
        ),
      ),
    );
  }
}

What changes dynamically?

  • The button text changes.
  • The follower count changes.
  • The action can be performed repeatedly.
  • All changes are triggered through setState().

41. Multiple UI Elements Can React to One State Variable

A single state variable can control multiple widgets.

bool isOnline = false;

The same state can control:

Text(
  isOnline ? 'Online' : 'Offline',
)

Icon(
  isOnline
      ? Icons.wifi
      : Icons.wifi_off,
)

ElevatedButton(
  onPressed: () {
    setState(() {
      isOnline = !isOnline;
    });
  },
  child: Text(
    isOnline ? 'Go Offline' : 'Go Online',
  ),
)

Changing isOnline updates all of these UI elements during the rebuild.


42. Dynamic UI State Table

State Type Example Possible UI Change
Integer counter Text, quantity, score
String message Text content
Boolean isLoading Show/hide widgets
Color backgroundColor Widget appearance
List tasks Dynamic list items
Double sliderValue Slider/value display
Enum selectedTab Selected screen/content

43. Common Mistakes

Mistake 1: Updating State Without setState()

counter++;

Use:

setState(() {
  counter++;
});

Mistake 2: Making setState() Async

setState(() async {
  await fetchData();
});

Perform asynchronous work outside the callback.

Mistake 3: Calling setState() After dispose()

Cancel timers, listeners, subscriptions, and other work when appropriate. Use mounted as a safeguard when necessary.

Mistake 4: Putting Heavy Work Inside setState()

Keep database operations, API calls, and expensive calculations outside the callback.

Mistake 5: Calling setState() Repeatedly Without Need

Combine related state updates where practical and avoid redundant rebuilds. :contentReference[oaicite:7]{index=7}


44. Best Practices for Dynamic UI

  • Keep state close to the widgets that use it when practical.
  • Use setState() only when the UI needs to respond to the state change.
  • Keep the setState() callback small.
  • Do not perform asynchronous work inside the callback.
  • Use mounted when an asynchronous operation may finish after widget disposal.
  • Cancel timers and subscriptions in dispose().
  • Use const widgets where possible.
  • Split very large widgets into smaller widgets.
  • Avoid unnecessary rebuilds.
  • For complex shared state, consider a dedicated state-management architecture.

45. setState() vs Direct Assignment

Direct Assignment Using setState()
Changes a Dart variable. Changes the variable and notifies Flutter.
Does not itself schedule a widget rebuild. Schedules the State object for rebuilding.
Suitable when the changed value does not affect this UI. Suitable when the changed value affects the UI.

46. Dynamic UI Update Example: Before and After

Initial State

int counter = 0;

UI:

Counter: 0

User Action

setState(() {
  counter++;
});

New State

int counter = 1;

UI becomes:

Counter: 1

The same process can happen for text, colors, lists, buttons, images, visibility, loading indicators, and other UI elements.


47. Interview Questions

Q1. What is dynamic UI in Flutter?

Dynamic UI is an interface that changes according to user interaction, application state, asynchronous data, or other runtime conditions.

Q2. How do you update UI dynamically using setState()?

Change the relevant state variable inside the setState() callback. Flutter then schedules the State object for rebuilding.

Q3. Why does the UI not always update when a variable changes?

Changing a state variable directly does not itself notify Flutter to rebuild the relevant widget.

Q4. Can I use await inside setState()?

No. The callback passed to setState() must not return a Future. Perform the asynchronous operation separately and then update the state synchronously.

Q5. What is mounted used for?

It can be checked before calling setState() after asynchronous work to verify that the State is still mounted.

Q6. Can multiple values be updated in one setState()?

Yes. Multiple related state variables can be changed inside one callback.

Q7. Why should unnecessary setState() calls be avoided?

Calling setState() can cause the relevant widget subtree to rebuild, so unnecessary calls can increase the work Flutter performs.


48. Practice Exercises

  1. Create a counter with Increase, Decrease, and Reset buttons.
  2. Create a button that changes its text after clicking.
  3. Create a box whose color changes between three colors.
  4. Create a show/hide password field.
  5. Create a favorite icon that changes when clicked.
  6. Create a dynamic shopping cart quantity selector.
  7. Create a to-do list with Add and Delete functionality.
  8. Create a loading button that displays a progress indicator for two seconds.
  9. Create a dropdown that dynamically displays the selected city.
  10. Create a slider that dynamically displays its numeric value.
  11. Create an expandable card using a Boolean state variable.
  12. Create a simple profile screen with Follow/Unfollow functionality.

49. Quick Revision

Concept Purpose
State Stores information that can change during runtime.
StatefulWidget Provides a widget structure that can maintain mutable state.
setState() Notifies Flutter that the State has changed and may need rebuilding.
build() Creates the widget configuration based on the current state.
mounted Indicates whether the State is currently mounted.
dispose() Used to clean up resources when State is permanently removed.

50. Official Flutter Resource

For detailed information about setState(), see the official Flutter API documentation:

Flutter setState() API Documentation


51. Flutter Training Resources

For structured Flutter training and practical learning resources, visit:

JustAcademy Flutter Training

To register for a course demo:

Register for Flutter Course Demo


52. Key Takeaways

  • Dynamic UI means that the interface changes while the application is running.
  • setState() is the basic Flutter mechanism for notifying a State object that its internal state has changed.
  • When setState() is called, Flutter schedules the associated State object for rebuilding.
  • The build() method uses the latest state to produce the updated UI.
  • Text, colors, buttons, lists, icons, loading indicators, switches, checkboxes, sliders, and other widgets can all react to state changes.
  • The setState() callback should be synchronous and focused on actual state changes.
  • Asynchronous work should be performed outside the setState() callback.
  • After asynchronous work, check mounted when necessary before updating state.
  • Cancel ongoing work such as timers and subscriptions during dispose() where appropriate.
  • Avoid unnecessary setState() calls because rebuilding widget subtrees can have an indirect performance cost. :contentReference[oaicite:8]{index=8}

Conclusion

Updating the UI dynamically using setState() is one of the most important Flutter concepts for building interactive applications. Whenever local state changes and that change should be reflected in the interface, setState() provides Flutter with the notification needed to rebuild the relevant UI. By practicing counters, forms, lists, loading states, switches, shopping carts, and other interactive examples, developers can build a strong foundation for more advanced Flutter state-management techniques.

whatsapp